/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.xd.manager.impl;

import com.xy.biz.xd.dao.TechniqueDao;
import com.xy.biz.xd.dao.TechniqueDocumentDao;
import com.xy.biz.xd.domain.bo.TechniqueBO;
import com.xy.biz.xd.domain.bo.TechniqueDocumentBO;
import com.xy.biz.xd.domain.converter.TechniqueConverter;
import com.xy.biz.xd.domain.converter.TechniqueDocumentConverter;
import com.xy.biz.xd.domain.po.TechniquePO;
import com.xy.biz.xd.domain.query.TechniqueByIdQuery;
import com.xy.biz.xd.domain.query.TechniqueQuery;
import com.xy.biz.xd.manager.TechniqueManager;
import com.xy.lang.domain.Result;
import com.xy.lang.enums.ApplyStatusEnum;
import com.xy.lang.enums.AuditStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zgy
 * @date 2022-1-11
 */
@Service
public class TechniqueManagerImpl implements TechniqueManager {

    @Autowired
    private TechniqueDao techniqueDao;
    @Autowired
    private TechniqueDocumentDao techniqueDocumentDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveTechnique(TechniqueBO techniqueBO) {
        List<TechniqueBO> techniqueBOList = listTechnique(TechniqueQuery.max()
                .goodsId(techniqueBO.getGoodsId())
                .status(ApplyStatusEnum.START.getCode())
                .build());
        if (!CollectionUtils.isEmpty(techniqueBOList) && !Objects.equals(true, techniqueBO.getCopyFlag())) {
            return -1;
        }
        TechniquePO techniquePO = TechniqueConverter.toPO(techniqueBO);
        int row = techniqueDao.saveTechnique(techniquePO);
        if (row > 0) {
            List<TechniqueDocumentBO> techniqueDocumentList = techniqueBO.getTechniqueDocumentList();
            if (!CollectionUtils.isEmpty(techniqueDocumentList)) {
                for (TechniqueDocumentBO techniqueDocumentBO : techniqueDocumentList) {
                    techniqueDocumentBO.setTechniqueDocumentId(null);
                    techniqueDocumentBO.setTechniqueId(techniquePO.getTechniqueId());
                }
                techniqueDocumentDao.saveAllTechniqueDocument(
                        TechniqueDocumentConverter.toPO(techniqueDocumentList));
            }

        }
        return row;
    }

    @Override
    public int saveAllTechnique(Collection<TechniqueBO> collection) {
        return techniqueDao.saveAllTechnique(TechniqueConverter.toPO(collection));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTechnique(TechniqueBO techniqueBO) {
        List<TechniqueBO> techniqueBOList = listTechnique(TechniqueQuery.max()
                .goodsId(techniqueBO.getGoodsId())
                .status(ApplyStatusEnum.START.getCode())
                .build());
        if (!CollectionUtils.isEmpty(techniqueBOList)) {
            if (Objects.equals(ApplyStatusEnum.START.getCode(), techniqueBO.getStatus())) {
                techniqueBOList = techniqueBOList.stream().filter(e -> !Objects.equals(e.getTechniqueId(), techniqueBO.getTechniqueId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(techniqueBOList)) {
                    return -1;
                }
            }
        }
        int row = techniqueDao.updateTechnique(TechniqueConverter.toPO(techniqueBO));
        if (row > 0) {
            if (CollectionUtils.isEmpty(techniqueBO.getTechniqueDocumentList())) {
                return row;
            }
            row = techniqueDocumentDao.deleteTechniqueDocumentByTechniqueId(techniqueBO.getTechniqueId());
            if (row < 1) {
                throw new RuntimeException("Description Failed to delete the Technique Document list");
            }
            List<TechniqueDocumentBO> techniqueDocumentBOList = techniqueBO.getTechniqueDocumentList();
            for (TechniqueDocumentBO techniqueDocumentBO : techniqueDocumentBOList) {
                techniqueDocumentBO.setTechniqueId(techniqueBO.getTechniqueId());
            }
            techniqueDocumentDao.saveAllTechniqueDocument(TechniqueDocumentConverter.toPO(techniqueDocumentBOList));
        }
        return row;
    }

    @Override
    public int copyTechnique(TechniqueBO techniqueBO) {
        List<TechniqueDocumentBO> techniqueDocumentBOList =
                TechniqueDocumentConverter.fromPO(
                        techniqueDocumentDao.listTechniqueDocumentByTechniqueId(Collections.singletonList(techniqueBO.getTechniqueId())));
        if (CollectionUtils.isEmpty(techniqueDocumentBOList)) {
            return -1;
        }
        techniqueBO.setCopyFlag(true);
        techniqueBO.setStatus(ApplyStatusEnum.DRAFT.getCode());
        techniqueBO.setAuditStatus(AuditStatusEnum.UNDO.getCode());
        techniqueBO.setAuditUserId(null);
        techniqueBO.setAuditTime(null);
        techniqueBO.setAuditUserName(null);
        techniqueBO.setAuditComment(null);
        techniqueBO.setTechniqueId(null);
        techniqueBO.setTechniqueDocumentList(techniqueDocumentBOList);
        return saveTechnique(techniqueBO);
    }

    @Override
    public int deleteTechnique(Long techniqueId) {
        return techniqueDao.deleteTechnique(techniqueId);
    }

    @Override
    public TechniqueBO getTechnique(TechniqueByIdQuery query) {
        TechniqueBO techniqueBO = TechniqueConverter.fromPO(techniqueDao.getTechnique(query.getTechniqueId()));
        build(query.getWithDocument(), query.getWithFlowHandleInfo(), Collections.singletonList(techniqueBO));
        return techniqueBO;
    }

    @Override
    public List<TechniqueBO> listTechniqueById(Collection<Long> collection) {
        return TechniqueConverter.fromPO(techniqueDao.listTechniqueById(collection));
    }

    @Override
    public List<TechniqueBO> listTechnique(TechniqueQuery query) {
        List<TechniqueBO> techniqueBOList = TechniqueConverter.fromPO(techniqueDao.listTechnique(query));
        build(query.getWithDocument(), false, techniqueBOList);
        return techniqueBOList;
    }

    public void build(boolean withDocument, boolean withFlowHandleInfo, List<TechniqueBO> techniqueBOList) {
        if (CollectionUtils.isEmpty(techniqueBOList)) {
            return;
        }
        Set<Long> techniqueIdSet = techniqueBOList.stream().map(TechniqueBO::getTechniqueId).collect(Collectors.toSet());
        Map<Long, List<TechniqueDocumentBO>> techniqueDocumentGroup = new HashMap<>();
        if (withDocument) {
            List<TechniqueDocumentBO> techniqueDocumentBOList
                    = TechniqueDocumentConverter.fromPO(techniqueDocumentDao.listTechniqueDocumentByTechniqueId(techniqueIdSet));
            techniqueDocumentGroup =
                    techniqueDocumentBOList.stream().collect(Collectors.groupingBy(TechniqueDocumentBO::getTechniqueId));
        }

        for (TechniqueBO techniqueBO : techniqueBOList) {
            if (techniqueDocumentGroup.containsKey(techniqueBO.getTechniqueId())) {
                techniqueBO.setTechniqueDocumentList(techniqueDocumentGroup.get(techniqueBO.getTechniqueId()));
            }
        }
    }

    @Override
    public int countTechnique(TechniqueQuery query) {
        return techniqueDao.countTechnique(query);
    }

}
